/*
 * IfStatementAst.cpp
 *
 *  Created on: 12 Nov 2010
 *      Author: kn308
 */

#include <sstream>
#include <MAlice/Codegen.h>
#include <MAlice/Ast/IfStatementAst.h>

namespace MAlice
{

IfStatementAst::IfStatementAst(ConditionalExpressionAst* conds)
{
	mTuples = new ListAst(conds);
}

IfStatementAst::IfStatementAst(ListAst* conds) :
	mTuples(conds)
{
}

IfStatementAst::~IfStatementAst()
{
	delete mTuples;
}

Value* IfStatementAst::generate()
{
	/*

	 cond
	 if.then:
	 ...
	 goto if.merge
	 if.else:
	 cond2
	 if.then:
	 ...
	 goto if.merge
	 if.merge

	 */

	Codegen* g = Codegen::get();
	Builder* builder = g->getBuilder();

	Function* F = builder->GetInsertBlock()->getParent();
	BasicBlock* mergeBB = BasicBlock::Create(g->getContext(), "if.merge");

	// if statement scope
	vector<Ast*>& tuples = mTuples->getChildren();
	for (vector<Ast*>::iterator i = tuples.begin(), e = tuples.end(); i != e; i++)
	{
		if (ConditionalExpressionAst* pair = dynamic_cast<ConditionalExpressionAst*> (*i))
		{
			// set weather its the last conditional of the if
			pair->setLast(i == --tuples.end());

			// the the merge block
			pair->setMerge(mergeBB);

			// perhaps scope
			g->pushScope();
			{
				pair->generate();
			}
			g->popScope();
		}
		else
		{
			stringstream ss;
			ss << "Invalid ConditionalExpressionAst node : " << *i  << ": '";
			ss << typeid(*i).name() << "' : " << &typeid(*i) << "!" << endl;
			throw runtime_error(ss.str());
		}
	}

	// set the insertion point to the merger of all if statements
	F->getBasicBlockList().push_back(mergeBB);
	builder->SetInsertPoint(mergeBB);

	return mergeBB;
}

}
